Vault
Search
CTRL + K
Vault
Search
CTRL + K
Chanho's Digital Garden
50 Logs
활동
Careerup 패키지
RPG 모의 경영 경진대회
SW 중심대학 공동 해커톤
창업 역량 강화 교육
후기
SW마에스트로 15기 합격 후기
AI
AI & Agents
Agent
Agent
AI 대화 기록의 개인정보 보존 정책
AI 에이전트 권한을 최소화하는 방법
AI 에이전트에 샌드박스와 승인 게이트가 필요한 이유
LLM 도구 호출에서 제안과 실행 분리하기
LLM 프롬프트를 코드처럼 버전 관리하기
구조화 출력으로 LLM 응답 파싱 안정화하기
멀티 에이전트 역할을 나누는 기준
사람의 승인을 영속 상태로 저장해야 하는 이유
스트리밍 응답의 취소와 오류 처리
에이전트 워크플로우를 상태 머신으로 표현하기
에이전트 작업을 샌드박스에서 실행하기
에이전트 재시도와 멱등성
토큰 비용을 기능 단위로 관측하기
프롬프트 인젝션을 데이터와 명령 분리로 줄이기
RAG
RAG
AI 응답에 출처와 근거를 연결하는 방법
Embedding 유사도만으로 검색하면 부족한 이유
Hybrid Search로 키워드와 의미 검색 결합하기
LLM 평가셋을 실제 실패 사례로 만드는 방법
RAG에서 Chunk 크기를 정하는 기준
Reranker를 추가할 때 얻는 것과 비용
환각을 없애기보다 검증 경로를 설계하기
claude code agent teams
Backend
Backend
NestJS
NestJS
DTO 검증과 도메인 검증은 무엇이 다른가
NestJS Guard와 Interceptor를 선택하는 기준
NestJS Module Provider Controller 역할 구분
Node.js
builtin
node.js builtin env
package
bcrypt
bodyParser
cookieParser
express-session
Node.js
Circuit Breaker로 연쇄 장애 줄이기
Cron 작업의 중복 실행 방지
Express 미들웨어의 실행 순서 이해하기
Express 서버의 백그라운드 작업을 명시적으로 시작하기
Express 에러 미들웨어가 네 개의 인자를 받는 이유
node.js express boilerplate
Node.js 서버의 Graceful Shutdown 구현하기
Node.js 이벤트 루프를 서버 요청의 흐름으로 이해하기
node에서 Redis 사용하기
Prisma N+1 쿼리를 발견하고 줄이는 방법
Prisma 트랜잭션의 두 가지 사용 방식
process.cwd와 __dirname의 차이를 실행 위치로 이해하기
Readiness와 Liveness Check의 차이
Timeout 없는 외부 API 호출이 위험한 이유
구조화 로그에 Request ID 넣기
대량 작업을 작은 청크로 나누는 방법
배치 작업을 재실행 가능하게 만드는 체크포인트
서비스 계층의 트랜잭션 경계 정하기
설정 검증을 애플리케이션 시작 시점에 해야 하는 이유
재시도에 지수 백오프와 지터가 필요한 이유
환경 변수를 설정과 비밀값으로 나누기
WEB
WEB
CORS
HTTP
JWT를 Base64 로 인코딩하는 이유
쿠키와 세션
Books
Books
AWS로 시작하는 인프라 구축의 정석
공허한 십자가
도둑맞은 집중력
도파민네이션
리액트를 다루는 기술
모던 자바스크립트 Deep Dive
박미정의 깃&깃허브 입문
스토너(초판본)
Coding Practice
Coding Practice
백준
백준
백준 1389번 - 케빈 베이컨의 6단계 법칙
백준 1504번 - 특정한 최단 경로
백준 1520번 - 내리막 길
백준 1717번 - 집합의 표현
백준 17472번 - 다리 만들기2
백준 1753번 - 최단경로
백준 2075번 - N번째 큰 수
백준 2156번 - 포도주 시식
백준 2887번 - 행성 터널
백준 3273번 - 두수의 합
백준 3665번 - 최종순위
백준 5582번 - 공통 부분 문자열
백준 9252번 - LCS 2
백준 9663번 - N-Queen
프로그래머스
프로그래머스
징검다리 건너기
Computer Science
Computer Science
ETC
ETC
Base64
Operating System
Operating System
Introduction to Operating Systems
Process
System Structure & Program Execution
Software Engineering
1인 개발자가 기술 부채의 우선순위를 정하는 방법
Software Engineering
레거시 코드에 Characterization Test 추가하기
알고리즘
2 pointer
알고리즘
Dynamic Programming
LCS
Union-Find
그래프 탐색 알고리즘(BFS,DFS)
백트래킹
브루트포스
알고리즘
연결성분 검사(connected component)
위상정렬
재귀함수
정렬 - 버블, 삽입, 선택, 계수
최단경로
최소신장트리
자료구조
자료구조
B-Tree
그래프
덱
동적 배열
스택, 큐
시간복잡도
연결리스트
우선 순위 큐
자료구조
트리
해쉬 테이블
힙
Database
Database
Index
Index
B+Tree 인덱스가 검색 범위를 줄이는 원리
Covering Index로 테이블 접근 줄이기
EXPLAIN과 EXPLAIN ANALYZE 읽는 순서
LIKE 검색이 인덱스를 타는 조건
MySQL 복합 인덱스의 순서와 중복 인덱스 판단하기
ORDER BY와 LIMIT을 위한 인덱스 설계
논리 삭제 컬럼을 인덱스에 포함할지 판단하기
복합 인덱스의 왼쪽 접두 규칙
슬로 쿼리 로그에서 개선 후보 찾기
인덱스 선택도가 성능에 미치는 영향
인덱스가 많아질수록 쓰기가 느려지는 이유
MYSQL
MYSQL
CHAR vs VARCHAR
날짜형 데이터 타입
Transaction
Transaction
MySQL InnoDB의 MVCC가 읽기를 처리하는 방법
SELECT FOR UPDATE를 사용할 때 주의할 점
Supabase Postgres에서 유한 재고 추첨을 원자적으로 처리하기
격리 수준과 Dirty Read Non-repeatable Read Phantom Read
낙관적 락과 비관적 락을 선택하는 기준
데드락이 생기는 이유와 재시도 전략
트랜잭션의 ACID를 실제 주문 처리로 이해하기
Auto Increment 식별자의 한계와 대안
Auto Increment의 문제점
Cache Aside 패턴과 캐시 무효화
CHECK Constraint와 애플리케이션 검증의 역할
DB 회원탈퇴처리
GROUP BY에서 집계 기준을 잘못 잡는 흔한 실수
INNER JOIN과 LEFT JOIN 결과 차이 이해하기
NULL은 값이 아니라 알 수 없음이다
Outbox Pattern으로 DB와 이벤트 발행 일치시키기
Postgres JSONB를 관계형 컬럼과 함께 쓰는 기준
Redis를 캐시로 사용할 때 원본 데이터와의 관계
SQL vs NoSQL
Unique Constraint를 비즈니스 규칙으로 활용하기
UUID v4와 시간 정렬 UUID 비교
UUID
관계형 데이터베이스의 관계
관계형 데이터베이스의 기본 키를 고르는 기준
물리삭제와 논리삭제
반정규화를 고려해야 하는 시점
상품명 정규화와 가격 그룹핑 파이프라인
서브쿼리와 JOIN 중 무엇을 선택할까
외래 키가 데이터 정합성을 지키는 방식
이상현상(anomaly)
자연 키와 인조 키의 장단점
자연키 vs 인조키
정규화
정규화가 중복과 이상 현상을 줄이는 원리
파티셔닝과 샤딩의 차이
DevOps
DevOps
AWS
AWS로 시작하는 인프라 구축 정리
AWS로 시작하는 인프라 구축 정리
1장 AWS 시작하기
3장 안전한 조작 준비하기
4장 가상 네트워크 만들기
5장 점프서버 준비하기
6장 웹 서버 준비하기
7장 로드 밸런서
8장 데이터베이스 서버 준비하기
9장 이미지 저장 장소 준비하기
10장 커스텀 도메인과 DNS 준비하기
11장 메일 서버 준비하기
12장 캐시 서버 준비하기
AWS
AWS VPC의 Public Subnet과 Private Subnet
CDN 캐시 키를 잘못 잡으면 생기는 문제
S3 Presigned URL로 업로드 부하 분산하기
Terraform State가 중요한 이유
로드 밸런서 Health Check 설계
CI-CD
CI-CD
Blue Green 배포와 Rolling 배포 비교
CI에서 의존성 캐시를 안전하게 사용하는 방법
Feature Flag로 배포와 출시 분리하기
GitHub Actions에서 비밀값 노출 막기
무중단 배포에서 DB 마이그레이션 순서
Docker
Docker
Docker Compose의 depends_on이 준비 완료를 뜻하지 않는 이유
Docker 이미지 레이어와 빌드 캐시 이해하기
Multi-stage Build로 이미지 크기 줄이기
컨테이너의 PID 1 문제와 시그널 처리
Git
Must Have 박미정의 깃&깃허브 입문 정리
1장 git 이란
2장 git 기본 명령어 알아보기
3장 git&github 기본 기능
4장 협업을 위한 github
5장 협업을 위한 git 명령어
6장 협업 기능 실습
7장 배포 자동화 github action
8장 커밋 이력 조작
Must Have 박미정의 깃&깃허브 입문 정리
Git
git worktree
git 명령어 정리
git 하위 폴더만 clone
git에서 remote 브랜치 지우기
Operations
Operations
RED Method로 API 모니터링 시작하기
RPO와 RTO로 복구 목표 정하기
백업이 아니라 복구를 테스트해야 하는 이유
분산 추적에서 Trace ID와 Span ID 역할
알람 피로를 줄이는 임계값 설계
운영 지표에서 평균보다 백분위수를 보는 이유
장애 대응 Runbook에 들어가야 할 내용
Frontend
Frontend
CSS
CSS
CSS Specificity를 낮게 유지하는 방법
Flexbox와 Grid를 선택하는 기준
Tailwind에서 디자인 토큰을 유지하는 방법
React
리액트를 다루는 기술 정리
1장 리액트 시작
2장 JSX
3장 컴포넌트
4장 이벤트 핸들링
5장 ref DOM에 이름달기
6장 컴포넌트 반복
7장 컴포넌트의 라이프사이클 메서드
8장 Hooks
9장 컴포넌트 스타일
10장 일정 관리 웹 애플리케이션 만들기
11장 컴포넌트 성능 최적화
12장 immer 사용해서 불변성 유지하기
리액트를 다루는 기술 정리
React
Controlled Component와 Uncontrolled Component 비교
Next.js Server Component와 Client Component 경계
Optimistic Update와 롤백 설계
React Context가 성능 문제를 만드는 경우
React Query에서 서버 상태를 따로 관리하는 이유
React 렌더링과 재렌더링의 차이
React에서 WebWorker사용하기
SSR Hydration 불일치가 생기는 이유
useEffect 의존성 배열을 거짓말하면 생기는 문제
useRef vs global Variable
useRef와 전역 변수의 차이
useState 업데이트가 즉시 반영되지 않는 이유
라우트 기반 코드 스플리팅의 효과
리스트 key에 index를 쓰면 생기는 문제
사용자 정의 컴포넌트 네이밍 오류
상태를 가까이 두는 것이 좋은 이유
서버 전용 환경 변수를 클라이언트에서 숨기기
에러 바운더리가 잡지 못하는 오류
cross-origin set cookie
Debounce와 Throttle을 선택하는 기준
웹 접근성을 위한 키보드 포커스 설계
Languages
Programming Languages
Programming Languages
JavaScript
MJS Deep dive 정리
4장 변수
5장 표현식과 문
6장 데이터 타입
7장 연산자
9장 타입 변환과 단축 평가
10장 객체 리터럴
11장 원시 값과 객체의 비교
12장 함수
13장 스코프
14장 전역 변수의 문제점
15장 let,const 키워드와 블록레벨스코프
16장 프로퍼티 어트리뷰트
17장 생성자 함수에 의한 객체 생성
18장 함수와 일급 객체
19장 프로토타입
20장 strict mode
21장 빌트인 객체
22장 this
23장 실행 컨텍스트
24장 클로저
25장 클래스
26장 ES6 함수의 추가 기능
27장 배열
28장 Number
29장 Math
30장 Date
31장 RegExp
32장 String
33장 7번째 데이터 타입 Symbol
34장 이터러블
35장 스프레드 문법
36장 디스트럭처링 할당
37장 Set과 Map
38장 브라우저의 렌더링 과정
39장 DOM
40장 이벤트
41장 타이머
42장 비동기 프로그래밍
43장 Ajax
44장 REST API
45장 프로미스
46장 제너레이터와 asyncawait
47장 에러처리
48장 모듈
49장 Babel과 Webpack
MJS Deep dive 정리
JavaScript
AbortController로 오래 걸리는 비동기 작업 취소하기
Array.from
CommonJS와 ESM을 함께 사용할 때 생기는 경계 문제
JavaScript 클로저가 상태를 보존하는 원리
JS toFixed에 대해서
localStorage와 sessionStorage
Map과 Object를 선택하는 실용적인 기준
Number vs parseInt vs +
Object.prototype를 상속받지 않는 객체
Promise.all이 항상 빠른 선택은 아닌 이유
setTimeout setImmediate process.nextTick 실행 순서 정리
Set으로 중복을 제거할 때 객체가 남는 이유
Web Worker
마이크로태스크와 매크로태스크의 실행 순서
백그라운드에서의 setInterval
부동소수점 오차를 금액 계산에서 피하는 방법
비동기 작업의 동시성을 제한하는 간단한 패턴
얕은 복사와 깊은 복사를 구분해야 하는 이유
전역 심벌과 로컬 심벌
Python
Python
python heapq 모듈
python stdin
TypeScript
TypeScript
never 타입으로 빠진 분기를 컴파일 시점에 찾기
TypeScript unknown과 any의 차이를 경계 코드로 이해하기
TypeScript 제네릭으로 타입 관계를 보존하는 방법
유니온 타입을 안전하게 좁히는 판별 필드 패턴
타입 단언보다 타입 가드를 먼저 써야 하는 이유
Mobile
Mobile
Flutter
Flutter
App Group UserDefaults와 Keychain의 역할 차이
BuildContext를 비동기 구간 뒤에 사용할 때 주의점
FCM 알림 탭과 앱 라우팅 연결하기
Flutter Navigator와 선언형 라우팅 비교
Flutter Widget의 불변성과 rebuild 이해하기
Flutter 이미지 캐시와 메모리 사용량 관리
Flutter와 iOS WidgetKit 사이에 데이터 공유하기
MethodChannel로 Flutter와 네이티브 코드 연결하기
StatefulWidget의 상태가 State 객체에 있는 이유
WidgetKit Timeline을 갱신하는 방법
다국어 앱에서 locale을 여러 런타임에 동기화하기
딥링크와 유니버설 링크의 차이
모바일 앱에서 Access Token을 저장하는 위치
앱 생명주기 변화에 안전하게 대응하기
WebView
WebView
React Native WebView 오프라인 런타임 설계
WebView 뒤로가기와 Native 내비게이션 연결
WebView 로그인 세션을 안전하게 전달하기
WebView 브릿지를 버전 있는 프로토콜로 만들기
WebView와 Native의 책임 경계
앱의 네트워크 상태를 신뢰하면 안 되는 이유
오프라인 큐에 멱등성이 필요한 이유
Projects
Projects
Agent Commons
Agent Commons
Agent Commons 플러그인 권한을 Manifest로 선언하기
Casa
Casa
Casa 가격 검색에서 이미지와 텍스트 유사도 결합하기
Casa 가격 추정값을 범위와 신뢰도로 표현하기
CasaTrade Elasticsearch 장애 시 검색 fallback 설계
CasaTrade 배치와 API가 도메인 로직을 공유하게 만들기
Goose Kuzi
Goose Kuzi
Goose Kuzi 추첨 API의 request ID 멱등성
Offline WebView
Offline WebView
Offline WebView 자산 번들을 원자적으로 교체하기
WMS Scanner
WMS Scanner
WMS 스캐너에서 네트워크 끊김과 중복 스캔 처리
Web
Web
browser
browser
Chrome의 프로세스 모델
브라우저 렌더링 과정을 DOM과 CSSOM부터 이해하기
브라우저 저장소 localStorage sessionStorage IndexedDB 비교
이벤트 버블링과 캡처링을 위임 패턴으로 이해하기
HTTP
HTTP
Access Token과 Refresh Token의 역할 분리
API 버전 관리에 URL과 헤더를 사용하는 방법
Base64는 암호화가 아니라 인코딩이다
CORS preflight 요청이 발생하는 조건
HTTP 캐시의 Cache-Control과 ETag 역할 구분하기
JWT의 서명과 암호화를 혼동하면 안 되는 이유
OAuth state와 PKCE가 막아주는 공격
Offset pagination과 Cursor pagination 비교
OpenAPI 스키마를 계약으로 유지하는 방법
Rate Limit을 사용자와 IP 중 어디에 걸어야 할까
Refresh Token Rotation으로 재사용 공격 줄이기
REST API에서 리소스 이름을 정하는 기준
SameSite 쿠키가 로그인 흐름에 미치는 영향
WebSocket과 Server-Sent Events 선택 기준
멱등적인 HTTP 메서드가 재시도에 중요한 이유
상태 코드 401과 403을 구분해서 사용하기
웹훅 서명을 검증해야 하는 이유
재시도 가능한 API에 Idempotency-Key 적용하기
파일 업로드에서 multipart form-data가 동작하는 방식
TypeScript
Languages
/ TypeScript
글 목록
유니온 타입을 안전하게 좁히는 판별 필드 패턴
2024.12.17
타입 단언보다 타입 가드를 먼저 써야 하는 이유
2024.12.24
never 타입으로 빠진 분기를 컴파일 시점에 찾기
2024.12.20
TypeScript 제네릭으로 타입 관계를 보존하는 방법
2024.12.13
TypeScript unknown과 any의 차이를 경계 코드로 이해하기
2024.12.10